/*
 * ﻿Copyright (C) 2012-2013 NewMain Softech
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package com.newmainsoftech.ant.script;

import java.util.List;

import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.types.Commandline.Argument;
import org.apache.tools.ant.types.LogLevel;
import org.apache.tools.ant.types.Path;

import com.newmainsoftech.ant.script.ReadMultiLineArgs.ArgPrefix;

public class JavaTaskUtil {
	private Java javaTask;
		public synchronized Java getJavaTask() {
			return javaTask;
		}
		public synchronized void setJavaTask( final Java javaTask) {
			this.javaTask = javaTask;
		}
		
	static enum ArgType {
		JvmArg, JavaArg;
	}
	
	void addArg( final Java javaTask, final String arg, final ArgType argType) {
		if ( javaTask == null) {
			throw new IllegalArgumentException( "javaTask input cannot be null.");
		}
		if ( arg == null) {
			throw new IllegalArgumentException( "arg input cannot be null.");
		}
		
		ArgType argTypeCopy = argType;
			if ( argTypeCopy == null) {
				argTypeCopy = ArgType.JavaArg;
			}
			switch( argTypeCopy) {
			case JavaArg:
			case JvmArg:
				break;
			default:
				throw new UnsupportedOperationException(
						String.format(
								"The argType input value (=%1$s) is unrecognized. " 
								+ "Code needs to be updated, please report this issue.", 
								argType.toString()
								)
						);
			} // switch
			
		String javaTaskName = javaTask.getTaskName();
			if ( javaTaskName == null) javaTaskName = "";
		String argCopy = arg.trim();
			if ( argCopy.length() < 1) {
				String format = null;
					switch( argTypeCopy) {
					case JavaArg:
						format 
						= String.format( 
								"Skiped to add arg input as an argument to java task%1$s because " 
								+ "arg input does not hold substantial string value."
								);
						break;
					case JvmArg:
						format 
						= String.format( 
								"Skiped to add arg input as an JVM argument to java task%1$s because " 
								+ "arg input does not hold substantial string value."
								);
						break;
					} // switch
				javaTask.log( 
						String.format(
								format, 
								((javaTaskName.length() < 1) ? "" : " (named as " + javaTaskName + ")")
								),
						LogLevel.WARN.getLevel()
						);
				return;
			}
		
		Argument argumentObj = null;
		String format = null;
			switch( argTypeCopy) {
			case JavaArg:
				argumentObj = javaTask.createArg();
				format = "Added next argument to java task %1$s: %2$s";
				break;
			case JvmArg:
				argumentObj = javaTask.createJvmarg();
				format = "Added next JVM argument to java task %1$s: %2$s";
				break;
			} // switch
			
		argumentObj.setValue( argCopy);
		
		javaTask.log(
				String.format( 
						format,
						((javaTaskName.length() < 1) ? "" : "(named as " + javaTaskName + ") "),
						argCopy
						), 
				LogLevel.DEBUG.getLevel()
				);
	}
	
	public void addArg( final Java javaTask, final String arg) {
		addArg( javaTask, arg, ArgType.JavaArg);
	}
	public void addArg( final String arg) {
		addArg( getJavaTask(), arg, ArgType.JavaArg);
	}
	
	public void addJvmArg( final Java javaTask, final String arg) {
		addArg( javaTask, arg, ArgType.JvmArg);
	}
	public void addJvmArg( final String arg) {
		addArg( getJavaTask(), arg, ArgType.JvmArg);
	}
	
	void  addArgs( final Java javaTask, final String args, final ArgPrefix argPrefix, final ArgType argType) {
		if ( javaTask == null) {
			throw new IllegalArgumentException( "javaTask input cannot be null.");
		}
		if ( args == null) {
			throw new IllegalArgumentException( "arg input cannot be null.");
		}
		
		ArgType argTypeCopy = argType;
			if ( argTypeCopy == null) {
				argTypeCopy = ArgType.JavaArg;
			}
			switch( argTypeCopy) {
			case JavaArg:
			case JvmArg:
				break;
			default:
				throw new UnsupportedOperationException(
						String.format(
								"The argType input value (=%1$s) is unrecognized. " 
								+ "Code needs to be updated, please report this issue.", 
								argType.toString()
								)
						);
			} // switch
		
		String javaTaskName = javaTask.getTaskName();
			if ( javaTaskName == null) javaTaskName = "";
		
		if ( args.trim().length() < 1) {
			String format = null;
				switch( argTypeCopy) {
				case JavaArg:
					format 
					= String.format( 
							"Skiped to add arguments from args input to java task%1$s because " 
							+ "args input does not hold substantial string values."
							);
					break;
				case JvmArg:
					format 
					= String.format( 
							"Skiped to add JVN arguments from args input to java task%1$s because " 
							+ "args input does not hold substantial string values."
							);
					break;
				} // switch
			javaTask.log( 
					String.format(
							format, 
							((javaTaskName.length() < 1) ? "" : " (named as " + javaTaskName + ")")
							),
					LogLevel.WARN.getLevel()
					);
			return;
		}
		
		ArgPrefix argPrefixCopy = argPrefix;
			if ( argPrefixCopy == null) {
				argPrefixCopy = ArgPrefix.Minus;
			}
		
		ReadMultiLineArgs readMultiLineArgs = new ReadMultiLineArgs();
			readMultiLineArgs.setPreFixStr( argPrefixCopy.getPrefix());
		List<String> splittedArgsList = readMultiLineArgs.splitByPrefix( args);
			if ( splittedArgsList.size() < 1) {
				javaTask.log( 
						String.format( 
								"Could not find an argument with %1$s prefix in args input " 
								+ "(=\"%2$s\") to add to java task%3$s.", 
								argPrefixCopy.getPrefix(),
								args,
								((javaTaskName.length() < 1) ? "" : "(named as " + javaTaskName + ") ")
								), 
						LogLevel.INFO.getLevel());
				return;
			}
		for( String arg : splittedArgsList) {
			Argument argument = null;
			String format = null;
				switch( argTypeCopy) {
				case JavaArg:
					argument = javaTask.createArg();
					format = "Added next argument to java task %1$s: %2$s";
					break;
				case JvmArg:
					argument = javaTask.createJvmarg();
					format = "Added next JVM argument to java task %1$s: %2$s";
					break;
				} // switch
			argument.setValue( arg);
			javaTask.log( 
					String.format( 
							format,
							((javaTaskName.length() < 1) ? "" : "(named as " + javaTaskName + ") "),
							arg
							), 
					LogLevel.DEBUG.getLevel());
		} // for
	}
	
	public void addArgs( final Java javaTask, final String args, final ArgPrefix argPrefix) {
		addArgs( javaTask, args, argPrefix, ArgType.JavaArg);
	}
	public void addArgs( final String args, final ArgPrefix argPrefix) {
		addArgs( getJavaTask(), args, argPrefix, ArgType.JavaArg);
	}
	
	public void addJvmArgs( final Java javaTask, final String args, final ArgPrefix argPrefix) {
		addArgs( javaTask, args, argPrefix, ArgType.JvmArg);
	}
	public void addJvmArgs( final String args, final ArgPrefix argPrefix) {
		addArgs( getJavaTask(), args, argPrefix, ArgType.JvmArg);
	}
	
	void addArgsAsPathFormat( 
			final Java javaTask, 
			final String args,  
			final ArgPrefix argPrefix, 
			final ArgType argType) 
	{
		if ( javaTask == null) {
			throw new IllegalArgumentException( "javaTask input cannot be null.");
		}
		if ( args == null) {
			throw new IllegalArgumentException( "arg input cannot be null.");
		}
		
		ArgPrefix argPrefixCopy = argPrefix;
			if ( argPrefixCopy == null) {
				argPrefixCopy = ArgPrefix.Minus;
			}
			
		String javaTaskName = javaTask.getTaskName();
			if ( javaTaskName == null) javaTaskName = "";
	
		ReadMultiLineArgs readMultiLineArgs = new ReadMultiLineArgs();
			readMultiLineArgs.setPreFixStr( argPrefixCopy.getPrefix());
			readMultiLineArgs.setConcatinateStr( ";");
		String argsInPathFormatStr = readMultiLineArgs.concatinate( args);
			if ( argsInPathFormatStr.length() < 1) {
				javaTask.log( 
						String.format(
								"Could not find an argument with %1$s prefix in args input " 
								+ "(=\"%2$s\") to add to java task%2$s.", 
								argPrefixCopy.getPrefix(), 
								args,
								((javaTaskName.length() < 1) ? "" : " (named as " + javaTaskName + ")")
								),
						LogLevel.WARN.getLevel()
						);
				return;
			}
		
		Path argsPath = new Path( javaTask.getProject(), argsInPathFormatStr);
		ArgType argTypeCopy = argType;
			if ( argTypeCopy == null) argTypeCopy = ArgType.JavaArg;
			
		String messageFormat;
		Argument argument;
			switch( argTypeCopy) {
			case JavaArg:
				argument = javaTask.createArg();
				messageFormat = "Added next arguments in path format to java task %1$s: %2$s";
				break;
			case JvmArg:
				argument = javaTask.createJvmarg();
				messageFormat = "Added next JVM arguments in path format to java task %1$s: %2$s";
				break;
			default:
				throw new UnsupportedOperationException(
						String.format(
								"The argType input value (=%1$s) is unrecognized. Code needs to be updated, " 
										+ "please report this issue.", 
										argType.toString()
								)
						);
			} // switch
			
		argument.setPath( argsPath);
		
		javaTask.log( 
				String.format( 
						messageFormat,
						((javaTaskName.length() < 1) ? "" : "(named as " + javaTaskName + ") "),
						argsInPathFormatStr
						), 
				LogLevel.DEBUG.getLevel());
	}
	
	public void addArgsAsPathFormat( final Java javaTask, final String args, final ArgPrefix argPrefix) {
		addArgsAsPathFormat( javaTask, args, argPrefix, ArgType.JavaArg);
	}
	public void addArgsAsPathFormat( final String args, final ArgPrefix argPrefix) {
		addArgsAsPathFormat( getJavaTask(), args, argPrefix, ArgType.JavaArg);
	}
	
	public void addJvmArgsAsPathFormat( final Java javaTask, final String args, final ArgPrefix argPrefix) {
		addArgsAsPathFormat( javaTask, args, argPrefix, ArgType.JvmArg);
	}
	public void addJvmArgsAsPathFormat( final String args, final ArgPrefix argPrefix) {
		addArgsAsPathFormat( getJavaTask(), args, argPrefix, ArgType.JvmArg);
	}
}
